import Menu from "../models/menu.model.js";
import logger from "../utils/logger.js";

class MenuService {
	// 创建菜单
	static async createMenu(menuData) {
		try {
			// 验证菜单名称是否已存在
			if (await Menu.isNameExist(menuData.name)) {
				throw new Error('菜单名称已存在');
			}
			
			// 验证父菜单是否存在
			if (menuData.parent_id && !(await Menu.findById(menuData.parent_id))) {
				throw new Error('父菜单不存在');
			}
			
			// 校验菜单类型和父级菜单关系
			await this.validateMenuTypeAndParent(menuData.menu_type, menuData.parent_id);
			
			const menu = await Menu.create(menuData);
			logger.info(`创建菜单成功: ${menuData.name}`);
			return menu;
		} catch (error) {
			logger.error(`创建菜单失败: ${error.message}`);
			throw error;
		}
	}

	// 校验菜单类型和父级菜单关系
	static async validateMenuTypeAndParent(menuType, parentId) {
		switch (parseInt(menuType)) {
			case 1: // 一级菜单
				if (parentId !== 0) {
					throw new Error("一级菜单的父级ID必须为0");
				}
				break;
			case 2: // 二级菜单
				if (parentId === 0) {
					throw new Error("二级菜单必须有父级菜单");
				}
				const parentMenu1 = await Menu.findById(parentId);
				if (!parentMenu1 || parentMenu1.menu_type !== 1) {
					throw new Error("二级菜单的父级必须是一级菜单");
				}
				break;
			case 3: // 三级菜单
				if (parentId === 0) {
					throw new Error("三级菜单必须有父级菜单");
				}
				const parentMenu2 = await Menu.findById(parentId);
				if (!parentMenu2 || parentMenu2.menu_type !== 2) {
					throw new Error("三级菜单的父级必须是二级菜单");
				}
				break;
			case 4: // 组件路由
				if (parentId === 0) {
					throw new Error("组件路由必须有父级菜单");
				}
				const parentMenu3 = await Menu.findById(parentId);
				if (!parentMenu3 || ![1, 2, 3].includes(parentMenu3.menu_type)) {
					throw new Error("组件路由的父级必须是一级、二级或三级菜单");
				}
				break;
			default:
				break;
		}
	}

	// 更新菜单
	static async updateMenu(id, menuData) {
		try {
			// 获取菜单信息
			const existMenu = await Menu.findById(id);
			if (!existMenu) {
				throw new Error("菜单不存在");
			}

			// 如果修改了父级菜单，检查是否有子菜单
			if (
				menuData.parent_id !== undefined &&
				menuData.parent_id !== existMenu.parent_id
			) {
				const hasChildren = await Menu.hasChildren(id);
				if (hasChildren) {
					throw new Error("该菜单下有子菜单，无法修改父级菜单");
				}

				// 校验菜单类型和父级菜单关系
				await this.validateMenuTypeAndParent(
					menuData.menu_type || existMenu.menu_type,
					menuData.parent_id
				);
			}

			// 如果修改了菜单类型，校验与父级菜单的关系
			if (
				menuData.menu_type !== undefined &&
				menuData.menu_type !== existMenu.menu_type
			) {
				await this.validateMenuTypeAndParent(
					menuData.menu_type,
					menuData.parent_id || existMenu.parent_id
				);

				// 如果修改为权限控制类型，需要清空路径和组件
				if (parseInt(menuData.menu_type) === 5) {
					menuData.path = null;
					menuData.component = null;
					menuData.icon = null;
				}

				// 如果从权限控制类型修改为其他类型，需要验证path和component是否已提供
				if (existMenu.menu_type === 5 && parseInt(menuData.menu_type) !== 5) {
					if (!menuData.path) {
						throw new Error("修改菜单类型为非权限控制类型时，路由路径不能为空");
					}
					if (!menuData.component) {
						throw new Error("修改菜单类型为非权限控制类型时，组件路径不能为空");
					}
				}
			}

			// 更新菜单
			const success = await Menu.update(id, menuData);
			if (!success) {
				throw new Error("菜单更新失败");
			}

			logger.info(`更新菜单成功: ID ${id}`);
			return await Menu.findById(id);
		} catch (error) {
			logger.error(`更新菜单失败: ${error.message}`);
			throw error;
		}
	}

	// 删除菜单
	static async deleteMenu(id) {
		try {
			// 检查菜单是否存在
			const menu = await Menu.findById(id);
			if (!menu) {
				throw new Error("菜单不存在");
			}

			// 递归删除菜单及其子菜单
			await Menu.recursiveSoftDelete(id);

			logger.info(`删除菜单成功: ID ${id}`);
			return true;
		} catch (error) {
			logger.error(`删除菜单失败: ${error.message}`);
			throw error;
		}
	}

	// 获取菜单树
	static async getMenuTree() {
		try {
			// 获取所有菜单
			const allMenus = await Menu.findAll();

			// 构建树形结构
			const menuTree = this.buildMenuTree(allMenus);

			return menuTree;
		} catch (error) {
			logger.error(`获取菜单树失败: ${error.message}`);
			throw error;
		}
	}

	// 构建菜单树
	static buildMenuTree(menus, parentId = 0) {
		const result = [];

		// 找出当前层级的菜单
		const currentLevelMenus = menus.filter(menu => menu.parent_id === parentId);

		// 遍历当前层级的菜单
		for (const menu of currentLevelMenus) {
			// 构建菜单节点
			const node = {
				...menu,
				children: this.buildMenuTree(menus, menu.id),
			};

			// 如果没有子节点，移除children属性
			if (node.children.length === 0) {
				delete node.children;
			}

			result.push(node);
		}

		return result;
	}

	// 获取用户菜单（根据角色ID）
	static async getUserMenus(roleId) {
		try {
			// 获取角色关联的菜单
			const roleMenus = await Menu.findMenusByRoleId(roleId);

			// 构建树形结构
			const menuTree = this.buildMenuTree(roleMenus);

			return menuTree;
		} catch (error) {
			logger.error(`获取用户菜单失败: ${error.message}`);
			throw error;
		}
	}
}

export default MenuService;
